package com.woniuxy.c_jdbcrealm;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;

/**
 * @author lg
 * @time 2020/07/04 14:10:08
 */
public class App {
    public static void main(String[] args) {
        //安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager ();

        //准备数据源
        DruidDataSource ds = new DruidDataSource ();
        ds.setDriverClassName ("com.mysql.cj.jdbc.Driver");
        ds.setUrl ("jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC");
        ds.setUsername ("root");
        ds.setPassword ("1370");

        //JdbcRealm是专门操作数据库的 ，也就是它封装了对数据库的操作
        //我们要告诉它，连接那个数据库
        JdbcRealm jdbcRealm = new JdbcRealm ();
        jdbcRealm.setDataSource (ds);

        //打招呼，认证查询时 ，连眼一起查出来
        jdbcRealm.setSaltStyle (JdbcRealm.SaltStyle.COLUMN);

        HashedCredentialsMatcher hbm = new HashedCredentialsMatcher ();
        hbm.setHashAlgorithmName ("MD5"); //所以的加密的方法
        hbm.setHashIterations (1024);// 1024次迭代

        jdbcRealm.setCredentialsMatcher (hbm); //加入到jdbcRealm中

        //设置认证的sql 语句
        jdbcRealm.setAuthenticationQuery ("select password,salt from users where username=?");
       // 根据用户信息 查询用户的角色
        jdbcRealm.setUserRolesQuery ("SELECT rname FROM users_roles ur INNER JOIN users u ON ur.`uid` = u.`uid` INNER JOIN roles r ON ur.rid = r.rid AND username = ?");
       //根据角色查询权限
        jdbcRealm.setPermissionsQuery ("SELECT pname FROM roles_permissions rp INNER JOIN roles r ON rp.`rid` = r.`rid` INNER JOIN permissions p ON rp.`pid` = p.`pid` AND rname = ?");
         // 设置许可查询表 （必须被指该项，否则无法判断用户拥有该叫色是否拥有某个权限）
        jdbcRealm.setPermissionsLookupEnabled (true);

        securityManager.setRealm (jdbcRealm);
        SecurityUtils.setSecurityManager (securityManager);

        Subject subject = SecurityUtils.getSubject ();
        UsernamePasswordToken token = new UsernamePasswordToken ("foo ", "123");

        try {
             //要在认证之前 ，把加密算法MD5,眼，迭代次数高数shiro
            subject.login (token);
            System.out.println ("ok");
        } catch (AuthenticationException e) {
            e.printStackTrace ();
            System.out.println ("not ok");
        }

        //授权
        System.out.println ("user:save " + subject.isPermitted ("user:save"));
        System.out.println ("user:delete " + subject.isPermitted ("user:delete"));
        System.out.println ("user:update " + subject.isPermitted ("user:update"));
        System.out.println ("user:find " + subject.isPermitted ("user:find"));

        subject.logout ();
    }
}
